package com.hertz.appr.service;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import com.hertz.appr.http.HttpClientManager;
import com.hertz.appr.pojo.CmdPojo;
import com.hertz.appr.pojo.db.Action;
import com.hertz.appr.pojo.db.Answer;
import com.hertz.appr.pojo.db.GuessResult;
import com.hertz.appr.pojo.db.Message;
import com.hertz.appr.pojo.db.PromoteResult;
import com.hertz.appr.pojo.db.Random;
import com.hertz.appr.pojo.db.Task;
import com.hertz.appr.service.cmd.v1.CmdPojoFactory;
import com.hertz.appr.service.cmd.v1.ICmdLineService;
import com.hertz.appr.util.CmdHelper;
import com.hertz.appr.util.Configuration;
import com.hertz.appr.util.Constants;
import com.hertz.appr.util.Util;

public class LotteryService {

	private Logger log = Logger.getLogger(LotteryService.class);
	
	private AnswerService answerService;
	private MessageService messageService;
	private ActionService actionService;
	private TaskService taskService;
	private RandomService randomService;
	private ResultService resultService;
	private RobotGang robotGang;
	private FriendShipService friendShipService;
	private ResultTemplateService resultTemplateService;
	private CmdPojoFactory cmdPojoFactory;
	
	private String provider;
	
	public LotteryService(String provider){
		this.provider = provider;
	}
	
	public void doLottery(String ymd){
		Random random = randomService.getRandom(ymd);
		if(random == null){
			log.info("no random,stop lottery");
			return;
		}
		
		List<Action> actionList = actionService.getActions(Action.ACTION_STATUS_WAITDEAL);
		if(actionList == null || actionList.size() == 0){
			log.info("no wait deal action,stop lottery");
			return;
		}else{
			for(Action a : actionList){
				boolean b = false;
				if(a.getType().equals(Action.ACTION_TYPE_GUESS)){
					b = guessLottery(a, random);
				}else if(a.getType().equals(Action.ACTION_TYPE_PROMOTE)){
					b = promoteLottery(a,random);
				}
				if(b){
					log.info("update action 2 finish,aid=" + a.getId());
					a.setStatus(Action.ACTION_STATUS_FINISH);
					a.setSystemTime(System.currentTimeMillis());
					actionService.updateAction(a);
				}
			}
		}
	}
	
	public void doLottery(){
		Date date = Calendar.getInstance().getTime();
		String ymd;
		try {
			ymd = Util.parseDate(date, "yyyy-MM-dd");
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("parse currentTime 2 ymd,error");
			e.printStackTrace();
			return;
		}
		doLottery(ymd);
	}
	
	
	public boolean guessLottery(Action a,Random random){
		log.info("start guess lottery");
		resultService.deleteResult(a);
		boolean b = false;
		String cmd = a.getValue();
		CmdPojo cmdPojo = null;
		try {
			cmdPojo = cmdPojoFactory.buildCmdPojo(cmd);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("parse action.value error,cmd=" + cmd);
			e.printStackTrace();
			return b;
		}
		if(cmdPojo == null){
			log.info("parse action.value error,cmd=" + cmd);
			return b;
		}
		Answer answer = answerService.getAnswerByActionId(a.getId(), provider);
		if(answer == null ){
			log.error("no answer,aid=" + a.getId());
			return b;
		}
		a.setAnswer(answer);
		
		List<Message> msgList = messageService.getMessageByAid(a.getId(), provider);
		//获取有抽奖资格的消息列表，符合答案要求，去掉删除的微博，第一次回复有效
		List<Message> readyList = getReadyLotteryList4Guess(msgList,a,answer,cmdPojo);
		if(readyList == null || readyList.size() == 0){
			log.info("this action no match msg,send result to actioner");
			Task task = new Task();
			task.setActionId(a.getId());
			task.setCreateTime(System.currentTimeMillis());
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("aidStr", ActionService.getActionId62Hex(a.getId()));
			data.put("tUrl", Configuration.getProperty(provider + ".t.baseurl") + a.getActionTid());
			String msg = resultTemplateService.getTemplateContent(Configuration.getProperty("tempname.no.reply"), data);
			task.setMsg(msg);
			task.setProvider(provider);
			task.setStatus(Task.TASK_STATUS_WAIT);
			task.setSystemTime(System.currentTimeMillis());
			task.setToNick(a.getNick());
			task.setToUid(a.getUid());
			task.setType(Task.TASK_TYPE_SEND_RESULT);
			task.setActionId(a.getId());
			task.setCreateTime(System.currentTimeMillis());
			task.setSourceTid(a.getActionTid());
			taskService.save(task);
			log.info("save " + task);
			b = true;
		}else{
			String countStr = "1";
			if(cmdPojo.getCl().hasOption(ICmdLineService.oCount)){
				countStr = cmdPojo.getCl().getOptionValue(ICmdLineService.oCount);
			}
			try {
					List<GuessResult> result = resultService.lotteryResult4Guess(readyList, Integer.valueOf(countStr),random);
					a.setRandomId(random.getYmd());
					a.setRandom(random);
					b = resultService.generateSendGuessResultTask(a,result);
			} catch (Exception e) {
				// TODO: handle exception
				log.error("guess lottery error: " + e.getMessage());
				e.printStackTrace();
				b = false;
				return b;
			}
		}
		log.info("end guess lottery,return " + b);
		return b;
	}
	
	public List<Message> getReadyLotteryList4Guess(List<Message> list,Action action,Answer answer,CmdPojo cmdPojo){
		List<Message> readyList = new ArrayList<Message>();
		List<String> readyListUid = new ArrayList<String>();
		String answerValue = answer.getValue();
		String about = "";
		Long aboutL = 0L;
		if(cmdPojo.getCl().hasOption(ICmdLineService.oInterval)){
			about = cmdPojo.getCl().getOptionValue(ICmdLineService.oInterval);
			if(StringUtils.isNumeric(about)){
				log.debug("action's about=" + about);
				aboutL = Long.valueOf(about);
			}else{
				log.info("action's about isNONumeric,about=" + about);
				about = "";
			}
		}
		if(list != null){
			log.debug(action);
			log.debug(answer);
			for(Message msg : list){
				String msgReply = msg.getValue();
				log.debug("reply = " + msgReply);
				if(StringUtils.isBlank(msgReply)){
					log.info("msg.value is blank");
					log.debug(msg);
					continue;
				}
				if(StringUtils.isNumeric(answerValue)){
					if(!StringUtils.isNumeric(msgReply)){
						log.info("answer is num,but reply isn't num");
						continue;
					}else{
						Long answerValueL = Long.valueOf(answerValue);
						Long msgReplyL = Long.valueOf(msgReply);
						if(msgReply.equals(answerValue) || (msgReplyL <= answerValueL + aboutL && msgReplyL >= answerValueL - aboutL)){
							if(!readyListUid.contains(msg.getUid())){
								readyList.add(msg);
								readyListUid.add(msg.getUid());
								log.info("add this msg to readyList.");
								log.debug(msg);
							}
						}
					}
					
				}else{
					if(msgReply.equals(answerValue)){
						readyList.add(msg);
						log.info("add this msg to readyList.");
						log.debug(msg);
					}
				}
			}
		}else{
			log.info("该活动没有参与者");
		}
		return readyList;
	}
	
	public boolean promoteLottery(Action a,Random random){
		resultService.deleteResult(a);
		boolean b = false;
		log.info("start promote lottery");
		String cmd = a.getValue();
		CmdPojo cmdPojo = null;
		try {
			cmdPojo = cmdPojoFactory.buildCmdPojo(cmd);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("parse action.value error,cmd=" + cmd);
			e.printStackTrace();
			return b;
		}
		if(cmdPojo == null){
			log.info("parse action.value error,cmd=" + cmd);
			return b;
		}
		
		List<Message> msgList = messageService.getMessageByAid(a.getId(), provider);
		List<PromoteResult> readyList = getReadyList4Promote(msgList,a,cmdPojo);
		if(readyList == null || readyList.size() == 0){
			log.info("this action no match msg,send result to actioner");
			Task task = new Task();
			task.setActionId(a.getId());
			task.setCreateTime(System.currentTimeMillis());
			Map<String, Object> data = new HashMap<String, Object>();
			data.put("aidStr", ActionService.getActionId62Hex(a.getId()));
			data.put("tUrl", Configuration.getProperty(provider + ".t.baseurl") + a.getActionTid());
			String msg = resultTemplateService.getTemplateContent(Configuration.getProperty("tempname.no.reply"), data);
			task.setMsg(msg);
			task.setProvider(provider);
			task.setStatus(Task.TASK_STATUS_WAIT);
			task.setSystemTime(System.currentTimeMillis());
			task.setToNick(a.getNick());
			task.setToUid(a.getUid());
			task.setType(Task.TASK_TYPE_SEND_RESULT);
			task.setActionId(a.getId());
			task.setCreateTime(System.currentTimeMillis());
			task.setSourceTid(a.getActionTid());
			taskService.save(task);
			log.info("save " + task);
			b = true;
		}else{
			String countStr = "1";
			if(cmdPojo.getCl().hasOption(ICmdLineService.oCount)){
				countStr = cmdPojo.getCl().getOptionValue(ICmdLineService.oCount);
			}
			String logic = ICmdLineService.oLogicRandom;
			if(cmdPojo.getCl().hasOption(ICmdLineService.oLogic)){
				logic = cmdPojo.getCl().getOptionValue(ICmdLineService.oLogic);
			}
			try {
				Integer count = Integer.valueOf(countStr);
				resultService.lotteryResult4Promote(readyList, count, random, logic);
				a.setRandomId(random.getYmd());
				a.setRandom(random);
				b = resultService.generateSendPromoteResultTask(a, readyList);
				b = true;
			} catch (Exception e) {
				// TODO: handle exception
				log.error("guess lottery error: " + e.getMessage());
				e.printStackTrace();
				b = false;
				return b;
			}
		}
		log.info("end guess lottery,return " + b);
		return b;
	}
	
	public List<PromoteResult> getReadyList4Promote(List<Message> msgList,Action a,CmdPojo cmdPojo){
		//key : uid
		Map<String, PromoteResult> map = new HashMap<String, PromoteResult>();
		Set<String> uidSet = new HashSet<String>();//在同一个活动中，每一个帐号仅能被@一次
//		boolean needFollow = false;//关注
//		boolean needNote = false;//评论
//		boolean needRepost = false;//转发
		String ats = "0";
//		if(cmdPojo.getCl().hasOption(ICmdOptionService.oFellow)){
//			needFollow = true;
//		}
//		if(cmdPojo.getCl().hasOption(ICmdOptionService.oNote)){
//			needNote = true;
//		}
//		if(cmdPojo.getCl().hasOption(ICmdOptionService.oRepost))
//			needRepost = true;
		if(cmdPojo.getCl().hasOption(ICmdLineService.oAt)){
			ats = cmdPojo.getCl().getOptionValue(ICmdLineService.oAt);
		}
		try {
			for(Message msg : msgList){
				PromoteResult pr = map.get(msg.getUid());
				if(pr == null){
					pr = new PromoteResult();
					pr.setFirstTime(msg.getCreateTime());
					pr.setSystemTime(System.currentTimeMillis());
				}
//				Boolean isFollowing = null;
//				if(needFollow){
//					isFollowing = friendShipService.isFollowing(msg.getUid(), a.getUid(), Configuration.QQ_PROVIDER);
//				}
				if(msg.getCreateTime() < pr.getFirstTime()){
					pr.setFirstTime(msg.getCreateTime());
				}
				pr.setUid(msg.getUid());
				pr.setNick(msg.getNick());
				pr.setProvider(msg.getProvider());
				pr.setActionId(msg.getActionId());
				//分析@帐号的有效性。
				String text = msg.getOrigtext();
				int c = 0;
				Matcher mAt = CmdHelper.atPattern.matcher(text);
				while(mAt.find()){
					String at = mAt.group();
					String uid = at.substring(1);
					uid = uid.trim();
					if(uidSet.contains(uid)){
						log.info("had @,uid=" + uid);
						continue;
					}
					if(isAppUid(uid, provider) || uid.equals(a.getUid()) || uid.equals(msg.getUid())){//本应用的大名，不算你@的好友。
						log.debug("un stat @ uid=" + uid);
					}else{
						if(hasUser(uid,provider)){
							uidSet.add(uid);
							c++;
						}
					}
				}
				pr.setToUserNum(pr.getToUserNum() + c);
				map.put(msg.getUid(), pr);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
			return null;
		}
		Set<String> set = map.keySet();
		List<PromoteResult> result = new ArrayList<PromoteResult>();
		for(String key : set){
			PromoteResult pr = map.get(key);
			if(Integer.valueOf(ats) <= pr.getToUserNum())
				result.add(map.get(key));
		}
		Collections.sort(result);
		return result;
		
	}
	public void lotteryResult(List<Message> list ,Action a){
		
	}
	/**
	 * wget t.qq.com/uid
	 * 根据页面返回内容，判断用户是否存在。
	 * @param uid
	 * @param provider
	 * @return
	 */
	public boolean hasUser(String uid,String provider){
		if(provider.equals(Configuration.QQ_PROVIDER)){
			String url = Constants.baseUrlQQ + uid;
			try {
				String content = HttpClientManager.get(url);
				if(content == null){
					return false;
				}else if(content.indexOf("用户不存在") >= 0){
					return false;
				}else{
					return  true;
				}
			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
				return false;
			}
		}else{
			return false;
		}
	}
	
	public boolean isAppUid(String uid,String provider){
		String appUid = Configuration.getProperty(provider + ".weibo.robot.uid");
		if(appUid.equals(uid)){
			return true;
		}else{
			return false;
		}
	}
	public ActionService getActionService() {
		return actionService;
	}

	public void setActionService(ActionService actionService) {
		this.actionService = actionService;
	}

	public String getProvider() {
		return provider;
	}

	public void setProvider(String provider) {
		this.provider = provider;
	}

	public MessageService getMessageService() {
		return messageService;
	}

	public void setMessageService(MessageService messageService) {
		this.messageService = messageService;
	}

	public TaskService getTaskService() {
		return taskService;
	}

	public void setTaskService(TaskService taskService) {
		this.taskService = taskService;
	}

	public RandomService getRandomService() {
		return randomService;
	}

	public void setRandomService(RandomService randomService) {
		this.randomService = randomService;
	}

	public ResultService getResultService() {
		return resultService;
	}

	public void setResultService(ResultService resultService) {
		this.resultService = resultService;
	}

	public RobotGang getRobotGang() {
		return robotGang;
	}

	public void setRobotGang(RobotGang robotGang) {
		this.robotGang = robotGang;
	}

	public FriendShipService getFriendShipService() {
		return friendShipService;
	}

	public void setFriendShipService(FriendShipService friendShipService) {
		this.friendShipService = friendShipService;
	}

	public AnswerService getAnswerService() {
		return answerService;
	}

	public void setAnswerService(AnswerService answerService) {
		this.answerService = answerService;
	}

	public ResultTemplateService getResultTemplateService() {
		return resultTemplateService;
	}

	public void setResultTemplateService(ResultTemplateService resultTemplateService) {
		this.resultTemplateService = resultTemplateService;
	}

	public CmdPojoFactory getCmdPojoFactory() {
		return cmdPojoFactory;
	}

	public void setCmdPojoFactory(CmdPojoFactory cmdPojoFactory) {
		this.cmdPojoFactory = cmdPojoFactory;
	}
	
}
